﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using WebApplication.MessageContent;
using WebApplication.BaseClass;
using WebApplication.Helper;

namespace WebApplication.MessageHandler
{
    public abstract class MessageHandler<TC>:IMessageHandler where TC:class,IMessageHandler,new()
    {
        protected static WeixinContext<TC> GlobalWeixinContext = new WeixinContext<TC>();

        protected WeixinContext<TC> WeixinContext
        {
            get { return GlobalWeixinContext; }
        }

        public TC CurrentMessageContext
        {
            get { return WeixinContext.GetMessageContext(RequestMessage); }
        }


        public string WeixinOpenid
        {
            get
            {
                if (RequestMessage != null)
                {
                    return RequestMessage.FromUserName;
                }
                return null;
            }
        }

        public bool CancelExcute { get; set; }

        public XDocument RequestDocument { get; set; }


        public XDocument ResponseDocument
        {
            get
            {
                if (ResponseMessage == null)
                {
                    return null;
                }
                return EntityHelper.ConvertEntityToXml(ResponseMessage as ResponseMessageBase);
            }
        }

        public IRequestMessageBase RequestMessage { get; set; }

        public IResponseMessageBase ResponseMessage { get; set; }


        public MessageHandler(XStreamingElement inputStream, int maxRecordCount = 0)
        {
            WeixinContext.MaxReocrdCount = maxRecordCount;
            using (XmlReader xr = XmlReader.Create(inputStream))
            {
                RequestDocument = XDocument.Load(xr);
                Init(RequestDocument);
            }
        }

        public MessageHandler(XDocument requestDocument, int maxRecordCount = 0)
        {
            WeixinContext.MaxReocrdCount = maxRecordCount;
            Init(requestDocument);
        }


        public void Execute()
        {
            if (CancelExcute)
            {
                return;
            }

            OnExecuting();

            if (CancelExcute)
            {
                return;
            }

            try
            {
                if (RequestMessage == null)
                {
                    return;
                }
                switch (RequestMessage.MsgType)
                {
                    case RequestMsgType.Text:
                        ResponseMessage = OnTextRequest(RequestMessage as RequestMessageText);
                        break;
                    case RequestMsgType.Location:
                        ResponseMessage = OnTextRequest(RequestMessage as RequestMessageLocation);
                        break;
                    case RequestMsgType.Image:
                        ResponseMessage = OnLocationRequest(RequestMessage as RequestMsessageImage);
                        break;
                    case RequestMsgType.Voice:
                        ResponseMessage = OnImageRequest(RequestMessage as RequestMessageVoice);
                        break;
                    case RequestMsgType.Video:
                        ResponseMessage = OnVideoRequest(RequestMessage as RequestMessageVido);
                        break;
                    case RequestMsgType.Event:
                        ResponseMessage = OnEventRequest(RequestMessage as RequestMessageEventBase);
                        break;
                    default:
                        throw new UnknownRequestMsgTypeException("未知的MsgType请求类型", null);
                }
                if (WeiXinContextGlobal.UserWeixinContext && ResponseMessage != null)
                {
                    WeixinContext.InsertMessage(ResponseMessage);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            finally
            {
                OnExecuted();
            }
        }

        public virtual void OnExecuting()
        {

        }

        public virtual void OnExecuted()
        {
        }

        private void Init(XDocument requestDocument)
        {
            RequestDocument = requestDocument;

            RequestMessage = RequestMessageFactory.GetRequestEntity(RequestMessage);

            if (WeiXinContextGlobal.UserWeixinContext)
            {
                WeixinContext.InsertMessage(RequestMessage);
            }
        }


        protected TR CreateResponseMessage<TR>() where TR : ResponseMessageBase
        {
            if (RequestMessage == null)
            {
                return null;
            }
            return ResquestMessage.CreateResponseMessage<TR>();
        }

        protected virtual IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
        {
            var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
            responseMessage.Content = "您发送的消息类型暂未被识别。";
            return responseMessage;
        }

        protected virtual IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }


        protected virtual IResponseMessageBase OnImageRequest(RequestMsessageImage requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }

        protected virtual IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }

        protected virtual IResponseMessageBase OnVidoRequest(RequestMessageVido requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }


        protected virtual IResponseMessageBase OnLinkRequest(RequestMessageLink requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }

        protected virtual IResponseMessageBase OnEventRequest(RequestMessageEventBase requestMessage)
        {
            var strongRequestMessage = RequestMessage as IRequestMessageEventBase;
            IResponseMessageBase responseMessage = null;
            switch (strongRequestMessage.Event)
            {
                case Event.LOCATION:
                    responseMessage = OnEvent_LocationRequest(RequestMessage as RequestMessageEvent_Location);
                    break;
                case Event.subscribe:
                    responseMessage = OnEvent_SubscribeRequest(RequestMessage as RequestMessageEvent_Subscribe);
                    break;
                case Event.unsubscribe:
                    responseMessage = OnEvent_UnSubscribeRequest(RequestMessage as RequestMessageEvent_Unsubscribe);
                    break;
                case Event.CLICK:
                    responseMessage = OnEvent_CLICKRequest(RequestMessage as RequestMessageEvent_Click);
                    break;
                case Event.scan:
                    responseMessage = OnEvent_ScanRequest(RequestMessage as RequestMessageEvent_Scan);
                    break;
                default:
                    throw new UnknownRequestMsgTypeException("未知的Event下属请求类型", null);
            }
            return responseMessage;
        }


        protected virtual IResponseMessageBase OnEvent_LocationRequest(RequestMessageEvent_Location requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }

        protected virtual IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }

        protected virtual IResponseMessageBase OnEvent_UnSubscribeRequest(RequestMessageEvent_Unsubscribe requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }

        protected virtual IResponseMessageBase OnEvent_CLICKRequest(RequestMessageEvent_Click requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }
        protected virtual IResponseMessageBase OnEvent_ScanRequest(RequestMessageEvent_Scan requestMessage)
        {
            return DefaultResponseMessage(requestMessage);
        }

    }
}